#include "battery.h"

Battery::Battery( QObject* parent ) : QObject( parent ) {
    QByteArray data( 8, 0x00 );
    data[ 0 ] = 0x01;                         //地址站号
    data[ 1 ] = 0x04;                         //功能码
    data[ 2 ] = 0x00;                         //寄存器高位字节
    data[ 3 ] = 0x60;                         //寄存器低位字节
    data[ 4 ] = 0x00;                         //读取寄存器数量高位字节
    data[ 5 ] = 0x44;                         //读取寄存器数量低位字节
    data[ 6 ] = static_cast< char >( 0xF0 );  // 16位检验码高位字节
    data[ 7 ] = 0x27;                         // 16位检验码低位字节
    sendDatas.append( data );
}

void Battery::sltBatteryInit() {

    Battery_control_com = new SerialPortObj( tr( "电池模块" ), Param::battery_port_name, Param::battery_baud_rate );
    connect( Battery_control_com, SIGNAL( sigReadData( QByteArray ) ), this, SLOT( sltBatteryRecvieData( QByteArray ) ) );
    connect( this, SIGNAL( sigSendData( SerialPortObj*, QByteArray ) ), Battery_control_com, SLOT( sltSendData( SerialPortObj*, QByteArray ) ) );
    Battery_control_com->init( false, 200 );

    //定时器，发送数据
    if ( Battery_control_com->isOpened() ) {
        QTimer* timer50ms = new QTimer();
        connect( timer50ms, SIGNAL( timeout() ), this, SLOT( slt50msTimer() ) );
        timer50ms->start( 1000 );
    }
    else {
        emit sigSendTips( "错误，电池模块串口打开失败" );
    }
}
void Battery::slt50msTimer() {

    if ( Battery_lose_connect_time++ >= 60 ) {
        emit sigLoseConnect( "电池模块" );
        Battery_lose_connect_time = 0;
    }
    if ( Battery_control_com->isOpened() ) { emit sigSendData( Battery_control_com, sendDatas ); }
}
void Battery::sltBatteryRecvieData( const QByteArray& data ) {
    Battery_lose_connect_time = 0;
    emit sigBatteryReceiveData( data, "Battery:" );
    // UPDATE 2022.10.25 过滤数据长度不正常的内容。解决：电量显示跳0问题
    if ( data.size() != 142 ) {
        qCritical() << "电池数据长度异常：data.size()=" << data.size();
        return;
    }
    ReadDatas = data;
}
QString Battery::GET_Value( EnumBattery Enum ) {
    QString str = "0";

    if ( Enum < ReadDatas.length() ) {
        switch ( Enum ) {
        case EnumBattery::MAX_VOLTAGE:
            str = QString::number( static_cast< double >( Reinterpret( ReadDatas[ Enum + 1 ], ReadDatas[ Enum ] ) ) / 1000.0 );
            break;
        case EnumBattery::MIN_VOLTAGE:
            str = QString::number( static_cast< double >( Reinterpret( ReadDatas[ Enum + 1 ], ReadDatas[ Enum ] ) ) / 1000.0 );
            break;
        case EnumBattery::MAX_VOLTAGE_NUM:
            str = QString::number( Reinterpret( ReadDatas[ Enum + 1 ], ReadDatas[ Enum ] ) );
            break;
        case EnumBattery::MIN_VOLTAGE_NUM:
            str = QString::number( Reinterpret( ReadDatas[ Enum + 1 ], ReadDatas[ Enum ] ) );
            break;
        case EnumBattery::MAX_TEMP_TEMP_EXCURSION_VALUE:
            str = QString::number( Reinterpret( ReadDatas[ Enum + 1 ], ReadDatas[ Enum ] ) - 40 );
            break;
        case EnumBattery::MIN_TEMP_TEMP_EXCURSION_VALUE:
            str = QString::number( Reinterpret( ReadDatas[ Enum + 1 ], ReadDatas[ Enum ] ) - 40 );
            break;
        case EnumBattery::MAX_TEMP_EXCURSION_NUM:
            str = QString::number( Reinterpret( ReadDatas[ Enum + 1 ], ReadDatas[ Enum ] ) );
            break;
        case EnumBattery::MIN_TEMP_EXCURSION_NUM:
            str = QString::number( Reinterpret( ReadDatas[ Enum + 1 ], ReadDatas[ Enum ] ) );
            break;
        case EnumBattery::CELL1_VOLTAGE:
        case EnumBattery::CELL2_VOLTAGE:
        case EnumBattery::CELL3_VOLTAGE:
        case EnumBattery::CELL4_VOLTAGE:
        case EnumBattery::CELL5_VOLTAGE:
        case EnumBattery::CELL6_VOLTAGE:
        case EnumBattery::CELL7_VOLTAGE:
        case EnumBattery::CELL8_VOLTAGE:
        case EnumBattery::CELL9_VOLTAGE:
        case EnumBattery::CELL10_VOLTAGE:
        case EnumBattery::CELL11_VOLTAGE:
        case EnumBattery::CELL12_VOLTAGE:
        case EnumBattery::CELL13_VOLTAGE:
        case EnumBattery::CELL14_VOLTAGE:
        case EnumBattery::CELL15_VOLTAGE:
        case EnumBattery::CELL16_VOLTAGE:
        case EnumBattery::CELL17_VOLTAGE:
        case EnumBattery::CELL18_VOLTAGE:
        case EnumBattery::CELL19_VOLTAGE:
        case EnumBattery::CELL20_VOLTAGE:
        case EnumBattery::CELL21_VOLTAGE:
        case EnumBattery::CELL22_VOLTAGE:
        case EnumBattery::CELL23_VOLTAGE:
        case EnumBattery::CELL24_VOLTAGE:
        case EnumBattery::CELL25_VOLTAGE:
        case EnumBattery::CELL26_VOLTAGE:
        case EnumBattery::CELL27_VOLTAGE:
        case EnumBattery::CELL28_VOLTAGE:
        case EnumBattery::CELL29_VOLTAGE:
        case EnumBattery::CELL30_VOLTAGE:
        case EnumBattery::CELL31_VOLTAGE:
        case EnumBattery::CELL32_VOLTAGE:
            str = QString::number( static_cast< double >( Reinterpret( ReadDatas[ Enum + 1 ], ReadDatas[ Enum ] ) ) / 1000.0 );
            break;
        case EnumBattery::TEMPERATURE1_TEMP_EXCURSION_VALUE:
            str = QString::number( Reinterpret( ReadDatas[ Enum + 1 ], ReadDatas[ Enum ] ) - 40 );
            break;
        case EnumBattery::TEMPERATURE2_TEMP_EXCURSION_VALUE:
            str = QString::number( Reinterpret( ReadDatas[ Enum + 1 ], ReadDatas[ Enum ] ) - 40 );
            break;
        case EnumBattery::TEMPERATURE3_TEMP_EXCURSION_VALUE:
            str = QString::number( Reinterpret( ReadDatas[ Enum + 1 ], ReadDatas[ Enum ] ) - 40 );
            break;
        case EnumBattery::TEMPERATURE4_TEMP_EXCURSION_VALUE:
            str = QString::number( Reinterpret( ReadDatas[ Enum + 1 ], ReadDatas[ Enum ] ) - 40 );
            break;
        case EnumBattery::TEMPERATURE5_TEMP_EXCURSION_VALUE:
            str = QString::number( Reinterpret( ReadDatas[ Enum + 1 ], ReadDatas[ Enum ] ) - 40 );
            break;
        case EnumBattery::TEMPERATURE6_TEMP_EXCURSION_VALUE:
            str = QString::number( Reinterpret( ReadDatas[ Enum + 1 ], ReadDatas[ Enum ] ) - 40 );
            break;
        case EnumBattery::SOC:
            str = QString::number( ReadDatas[ Enum + 1 ] );
            break;
        case EnumBattery::SOH:
            str = QString::number( ReadDatas[ Enum + 1 ] );
            break;
        case EnumBattery::PackChaCur:
            str = QString::number( ( Reinterpret( ReadDatas[ Enum + 1 ], ReadDatas[ Enum ] ) - 10000 ) / 10.0 );
            break;
        case EnumBattery::PackDisCur:
            str = QString::number( ( Reinterpret( ReadDatas[ Enum + 1 ], ReadDatas[ Enum ] ) - 10000 ) / 10.0 );
            break;
        case EnumBattery::ALL_CELL_VOLTAGE:

            str = QString::number( static_cast< double >( Reinterpret( ReadDatas[ Enum + 1 ], ReadDatas[ Enum ] ) ) / 10.0 );
            break;
        case EnumBattery::MEASURING_CURRENT:
            str = QString::number( static_cast< double >( Reinterpret( ReadDatas[ Enum + 1 ], ReadDatas[ Enum ] ) - 10000 ) / 10.0 );
            break;
        case EnumBattery::gstcSysVar_CellWorkState:
            str = "0x0000" + QString::number( Reinterpret( ReadDatas[ Enum + 3 ], ReadDatas[ Enum + 2 ], ReadDatas[ Enum + 1 ], ReadDatas[ Enum ] ), 16 );
            break;
        case EnumBattery::gstcSysVar_ShortTime:
            str = QString::number( Reinterpret( ReadDatas[ Enum + 1 ], ReadDatas[ Enum ] ) );
            break;
        case EnumBattery::gstcSysVar_ChargingTime:
            str = QString::number( Reinterpret( ReadDatas[ Enum + 1 ], ReadDatas[ Enum ] ) );
            break;
        case EnumBattery::gstcSysVar_unSwProtectStatus_word:
            str = "0x0000" + QString::number( Reinterpret( ReadDatas[ Enum + 1 ], ReadDatas[ Enum ] ), 16 );
            break;
        case EnumBattery::gstcSysVar_ChargeTime:
            str = QString::number( Reinterpret( ReadDatas[ Enum + 3 ], ReadDatas[ Enum + 2 ], ReadDatas[ Enum + 1 ], ReadDatas[ Enum ] ) );
            break;
        case EnumBattery::gstcSysVar_DischargeTime:
            str = QString::number( Reinterpret( ReadDatas[ Enum + 3 ], ReadDatas[ Enum + 2 ], ReadDatas[ Enum + 1 ], ReadDatas[ Enum ] ) );
            break;
        case EnumBattery::gstcSysVar_MaxChargeInterval:
            str = QString::number( Reinterpret( ReadDatas[ Enum + 3 ], ReadDatas[ Enum + 2 ], ReadDatas[ Enum + 1 ], ReadDatas[ Enum ] ) );
            break;
        case EnumBattery::gstcSysVar_MaxDischargeInterval:
            str = QString::number( Reinterpret( ReadDatas[ Enum + 3 ], ReadDatas[ Enum + 2 ], ReadDatas[ Enum + 1 ], ReadDatas[ Enum ] ) );
            break;
        case EnumBattery::gstcSysVar_BalancehState:
            str = QString::number( Reinterpret( ReadDatas[ Enum + 3 ], ReadDatas[ Enum + 2 ], ReadDatas[ Enum + 1 ], ReadDatas[ Enum ] ) );
            break;
        case EnumBattery::gstcSysVar_CyclesTime:
            str = QString::number( Reinterpret( ReadDatas[ Enum + 1 ], ReadDatas[ Enum ] ) );
            break;
        }
    }
    return str;
}

bool Battery::getFaultState( QString& result ) {
    int fault = Reinterpret( ReadDatas[ gstcSysVar_unSwProtectStatus_word + 1 ], ReadDatas[ gstcSysVar_unSwProtectStatus_word ] );
    if ( ( fault & 0xff ) == 0x00 ) {
        result = "无故障";
        return false;
    }
    else {
        if ( ( fault & 0x01 ) == 0x01 )
            result = "充电过压报警";
        else if ( ( ( fault >> 1 ) & 0x01 ) == 0x01 )
            result = "放电欠压报警";
        else if ( ( ( fault >> 2 ) & 0x01 ) == 0x01 )
            result = "充电过流报警";
        else if ( ( ( fault >> 3 ) & 0x01 ) == 0x01 )
            result = "放电过流报警1";
        else if ( ( ( fault >> 4 ) & 0x01 ) == 0x01 )
            result = "放电过流报警2";
        else if ( ( ( fault >> 5 ) & 0x01 ) == 0x01 )
            result = "短路报警";
        else if ( ( ( fault >> 6 ) & 0x01 ) == 0x01 )
            result = "充电高温报警";
        else if ( ( ( fault >> 7 ) & 0x01 ) == 0x01 )
            result = "充电低温报警";
        else if ( ( ( fault >> 8 ) & 0x01 ) == 0x01 )
            result = "放电高温报警";
        else if ( ( ( fault >> 9 ) & 0x01 ) == 0x01 )
            result = "放电低温报警";
        else if ( ( ( fault >> 10 ) & 0x01 ) == 0x01 )
            result = "压差故障报警";
        else if ( ( ( fault >> 11 ) & 0x01 ) == 0x01 )
            result = "DC-DC温度报警";
        else if ( ( ( fault >> 12 ) & 0x01 ) == 0x01 )
            result = "SOC低报警";
        else if ( ( ( fault >> 13 ) & 0x01 ) == 0x01 )
            result = "绝缘故障报警";
        return true;
    }
}
short Battery::Reinterpret( char L, char H ) {
    QByteArray by( 2, 0x00 );
    by[ 0 ] = L;
    by[ 1 ] = H;
    return *reinterpret_cast< const short* >( by.data() );
}
int Battery::Reinterpret( char L, char H8, char H16, char H24 ) {
    QByteArray by( 4, 0x00 );
    by[ 0 ] = L;
    by[ 1 ] = H8;
    by[ 2 ] = H16;
    by[ 3 ] = H24;
    return *reinterpret_cast< const int* >( by.data() );
}
